﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace DbSharp.SupportLib.Crypto
{
    public class RsaSign
    {
        private void test()
        {
            byte[] data = Encoding.UTF8.GetBytes("Message to sign");
            byte[] publicKey;
            byte[] signature;

            // Our chosen hashing algorithm.
            object hasher = SHA1.Create();         

            // Generate a new key pair, then sign the data with it:
            using (var publicPrivateRsa = new RSACryptoServiceProvider())
            {
                signature = publicPrivateRsa.SignData(data, hasher);
                publicKey = publicPrivateRsa.ExportCspBlob(false);    // get public key
            }

            // Create a fresh RSA using just the public key, then test the signature.
            using (var publicOnlyRsa = new RSACryptoServiceProvider())
            {
                publicOnlyRsa.ImportCspBlob(publicKey);
                Console.Write(publicOnlyRsa.VerifyData(data, hasher, signature)); // True

                // Let's now tamper with the data, and recheck the signature:
                data[0] = 0;
                Console.Write(publicOnlyRsa.VerifyData(data, hasher, signature)); // False

                // The following throws an exception as we're lacking a private key:
                signature = publicOnlyRsa.SignData(data, hasher);
            }
        }

        public string GetKeyXmlFromFile(string keyXmlFile)
        {
            string result = string.Empty;
            using (StreamReader reader = new StreamReader(keyXmlFile, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }
            return result;
        }

        public void Sign(string oldBase64Text, string privateKeyXML, out string signatureBase64Text)
        {
            byte[] data = Convert.FromBase64String(oldBase64Text);
            byte[] signature;

            // Our chosen hashing algorithm.
            object hasher = SHA1.Create();         

            // Generate a new key pair, then sign the data with it:
            using (var publicPrivateRsa = RsaCryptoService.PrepareRSA())
            {
                publicPrivateRsa.FromXmlString(privateKeyXML);
                signature = publicPrivateRsa.SignData(data, hasher);
            }
            signatureBase64Text= Convert.ToBase64String(signature);
        }

        //public void Sign2(string oldBase64Text, string privateKeyFile, out string signatureBase64Text)
        //{
        //    string publicPrivateKeyXML = GetXmlFromKeyFile(privateKeyFile);
        //    Sign(oldBase64Text, publicPrivateKeyXML, out signatureBase64Text);
        //}

        public bool Verify(string oldBase64Text, string publicKeyXML, string signatureBase64Text)
        {
            bool result;
            try
            {
                byte[] data = Convert.FromBase64String(oldBase64Text);
                byte[] signature = Convert.FromBase64String(signatureBase64Text);

                // Our chosen hashing algorithm.
                object hasher = SHA1.Create();

                // Create a fresh RSA using just the public key, then test the signature.
                using (var publicOnlyRsa = RsaCryptoService.PrepareRSA())
                {
                    publicOnlyRsa.FromXmlString(publicKeyXML);

                    result = publicOnlyRsa.VerifyData(data, hasher, signature);
                }
            }
            catch
            {
                result = false;
            }

            return result;
        }

        //public bool Verify2(string oldBase64Text, string publicKeyFile, string signatureBase64Text)
        //{
        //    string publicKeyXML = GetXmlFromKeyFile(publicKeyFile);
        //    return Verify(oldBase64Text, publicKeyXML, signatureBase64Text);
        //}
    }
}
